package com.zizo.autohome.tfidf;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.seg.common.Term;
import com.zizo.util.ConnectionPool;

public class TFIDFImp implements Runnable {
	private Map<String, Integer> countMap = new HashMap<>();// 出现次数的Map（以帖子算）
	private Map<String, Double> rateMap = new HashMap<>();// 词的频率Map（value=总次数--以词算）
	private int allCount;// 所有车的总帖子数
	private Connection conn168;
	private Connection conn198;
	private int cid;// 车型ID(KB)
	private String tablename;// 要存储的表名称
	private int allWordCnt;// 所有词的总数量

	public TFIDFImp(int allCount, Connection conn168, Connection conn198, int cid, String tablename) {
		super();
		this.allCount = allCount;
		this.conn168 = conn168;
		this.conn198 = conn198;
		this.cid = cid;
		this.tablename = tablename;
	}

	/**
	 * @Title: getBBSData
	 * @Description: 从论坛中获取
	 * @return void
	 * @author Alexis
	 */
	public void getBBSData() {
		Statement st = null;
		ResultSet rs = null;
		int bbsid = getBBSID();
		if (bbsid == 0) {
			return;
		}
		String sql = "SELECT CONCAT(bbs_title,' ',bbs_content) FROM bbs_c_" + bbsid;
		try {
			st = conn168.createStatement();
			rs = st.executeQuery(sql);
			while (rs.next()) {
				String sentence = rs.getString(1);
				calSentence(sentence);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				rs.close();
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * @Title: getFilterData
	 * @Description: TODO 去掉停止词
	 * @param content
	 * @return
	 * @return String
	 * @author Alexis
	 */
	public static final String getFilterData(String content) {
		String s = "^\\?|^的$|^了$|^我$|^是$|^在$|^有$|^就$|^也$|^一$|^都$|^个$|^和$|^说$|^这$|^要$|^去$|^还$|^到$|^啊$|^你$|^吗$|^给$|^看$|^就是$|^吧$|^呀$|^但$|^为$|^及$|^我的$|^我们$|^你们$|^刚$|^总体$|^因为$|^所以$|^但是$|^方面$|^可能$|^还是$|^这是$|^那$|^那是$|^能$|^呢$|^才$|^那么$|^这么$|^然后$|^然而$|^只有$|^什么$|^总的来说$|^哪个$|^到底$|^不知$|^这些$|^那些$|^射精$|^版主$|^认证$";
		Pattern p_1 = Pattern.compile(s);
		Matcher m_1 = p_1.matcher(content);
		String res_1 = m_1.replaceAll("");
		p_1 = null;
		m_1 = null;
		return res_1;
	}

	/**
	 * @Title: getKBData
	 * @Description: 从口碑中获取内容
	 * @return void
	 * @author Alexis
	 */
	public void getKBData() {
		Statement st = null;
		ResultSet rs = null;
		String sql = "SELECT kb_content FROM autohome_kb WHERE kb_cid=" + cid;
		try {
			st = conn168.createStatement();
			rs = st.executeQuery(sql);
			while (rs.next()) {
				String sentence = rs.getString(1);
				calSentence(sentence);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				rs.close();
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * @Title: getBBSID
	 * @Description: 根据车型ID得到对应的论坛ID
	 * @return void
	 * @author Alexis
	 */
	public int getBBSID() {
		String sql = "SELECT autohome_autohomeClubId FROM carvoice_core.core_brand_autohome WHERE autohome_autohomeId="
				+ cid;
		Statement st = null;
		ResultSet rs = null;
		int bbsid = 0;
		try {
			st = conn168.createStatement();
			rs = st.executeQuery(sql);
			if (rs.next()) {
				bbsid = rs.getInt(1);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				rs.close();
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return bbsid;
	}

	/**
	 * @Title: calSentence
	 * @Description: 计算
	 * @param sentence
	 * @return void
	 * @author Alexis
	 */
	public void calSentence(String sentence) {
		String sen = TFUtil.getFilterData(sentence);// 去除特殊标点
		List<Term> wordList = HanLP.segment(sen);// 分词
		sen = null;
		double size = wordList.size();// 词语的总数量
		allWordCnt += size;// 总数量相加
		Map<String, Integer> wordMap = new HashMap<>();// 当前句子的map，用于记录每个词的出现次数
		/* 计算词在当前句子种出现的次数 */
		for (Term term : wordList) {
			String word = getFilterData(term.word.replaceAll("\\}\\{", "").trim());
			if (word.length() < 1) {
				continue;
			}
			if (wordMap.containsKey(word)) {
				wordMap.put(word, wordMap.get(word) + 1);
			} else {
				wordMap.put(word, 1);
			}
		}
		wordList = null;
		/* 往总Map表中添加 */
		for (Map.Entry<String, Integer> entry : wordMap.entrySet()) {
			double rate = entry.getValue();// 当前词的出现次数
			String word = entry.getKey();// 当前词
			if (countMap.containsKey(word)) {
				countMap.put(word, countMap.get(word) + 1);
				rateMap.put(word, rateMap.get(word) + rate);
			} else {
				countMap.put(word, 1);
				rateMap.put(word, rate);
			}
			word = null;
		}
		wordMap = null;
	}

	/**
	 * @Title: calTFIDF
	 * @Description: 计算TF-IDF
	 * @return void
	 * @author Alexis
	 */
	public void calTFIDF() {
		for (Map.Entry<String, Double> entry : rateMap.entrySet()) {
			String word = entry.getKey();
			double tf = entry.getValue() / allWordCnt;
			int count = countMap.get(word);// 当前词的出现的帖子数
			insertTf_Idf(word, tf);
			insertTotal(word, count, allCount);
			word = null;
		}
	}

	/**
	 * @Title: insert
	 * @Description: 插入TF-IDF的值
	 * @param word
	 * @param value
	 * @return void
	 * @author Alexis
	 */
	public void insertTf_Idf(String word, double tf) {
		PreparedStatement ps = null;
		String sql = "INSERT INTO " + tablename + "(word,tf) values(?,?)";
		try {
			ps = conn198.prepareStatement(sql);
			ps.setString(1, word);
			ps.setDouble(2, tf);
			ps.executeUpdate();
		} catch (SQLException e) {
			System.out.println(word);
		} finally {
			try {
				ps.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * @Title: insert
	 * @Description: 插入TF-IDF的值
	 * @param word
	 * @param value
	 * @return void
	 * @author Alexis
	 */
	public void insertTotal(String word, int cnt, int total) {
		PreparedStatement ps = null;
		String sql = "INSERT INTO total(word,cnt,total) values(?,?,?)";
		try {
			ps = conn198.prepareStatement(sql);
			ps.setString(1, word);
			ps.setInt(2, cnt);
			ps.setInt(3, total);
			ps.executeUpdate();
		} catch (SQLException e) {
			System.out.println(word);
		} finally {
			try {
				ps.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * @Title: createTable
	 * @Description: 创建表
	 * @return void
	 * @author Alexis
	 */
	public void createTable() {
		String sql = "DROP TABLE IF EXISTS " + tablename;
		String sql1 = "CREATE TABLE " + tablename + " like tf_idf";
		Statement st = null;
		try {
			st = conn198.createStatement();
			st.executeUpdate(sql);
			st.executeUpdate(sql1);
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	public void run() {
		createTable();
		getBBSData();
		getKBData();
		calTFIDF();
		System.out.println(cid + " GG!");
	}

	public List<Integer> getKBIDS() {
		Statement st = null;
		ResultSet rs = null;
		String sql = "SELECT brand_autohome FROM carvoice_biz.biz_brand";
		List<Integer> list = new ArrayList<Integer>();
		try {
			st = conn168.createStatement();
			rs = st.executeQuery(sql);
			while (rs.next()) {
				list.add(rs.getInt(1));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				rs.close();
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return list;
	}

	/**
	 * @Title: getAllPost
	 * @Description: 得到所有的帖子量
	 * @param list
	 * @return
	 * @return int
	 * @author HeYan
	 */
	public int getAllPost(List<Integer> list) {
		StringBuilder sb = new StringBuilder();
		sb.append("'autohome_kb'");
		for (int i : list) {
			String s = "'bbs_c_" + i + "'";
			sb.append("," + s);
		}
		String sql = "SELECT SUM(TABLE_ROWS) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='autohome_syn' AND TABLE_NAME IN ("
				+ sb.toString() + ") GROUP BY TABLE_SCHEMA";
		Statement st = null;
		ResultSet rs = null;
		int res = 0;
		try {
			st = conn168.createStatement();
			rs = st.executeQuery(sql);
			if (rs.next()) {
				res = rs.getInt(1);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				rs.close();
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return res;
	}

	public static void main(String[] args) {
		long start = System.currentTimeMillis();
		Connection conn168 = ConnectionPool.getConnection("autohome_syn", "192.169.0.168");
		Connection conn198 = ConnectionPool.getConnection("TF-IDF", "localhost");
		ExecutorService fix = Executors.newFixedThreadPool(30);
		TFIDFImp tf = new TFIDFImp(0, conn168, conn198, 364, "tf_idf_364");
		List<Integer> list = tf.getKBIDS();
		int allCount = tf.getAllPost(list);
		for (int i : list) {
			fix.execute(new TFIDFImp(allCount, conn168, conn198, i, "tf_idf_" + i));
		}
		fix.shutdown();
		while (true) {
			if (fix.isTerminated()) {
				System.out.println((System.currentTimeMillis() - start) / (1000 * 60) + "Minute");
				break;
			} else {
				try {
					Thread.sleep(1000 * 600);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
